use std::fs::{self, File};

use getifaddrs::getifaddrs;
use std::net::{IpAddr};

use qrcode_generator::QrCodeEcc;
use base64::Engine as _;
use std::io::Read;
use std::io;
use serde::{Deserialize, Serialize};
use std::path::{Path, PathBuf};
use std::env;
use std::io::Write;


pub fn get_local_url() -> String {
    // 获取本地活跃IP
    let mut active_ip :IpAddr = "127.0.0.1".parse().unwrap();
    let mut first_ip = false;
    match getifaddrs() {
        Ok(interfaces) => {
            //println!("本地活跃IP地址:");
            for iface in interfaces {
                // 检查接口是否活跃
                if iface.flags.contains(getifaddrs::InterfaceFlags::RUNNING) {
                    // address 字段现在直接是 IpAddr 类型，无需 Option 匹配
                    let addr = iface.address;
                    
                    match addr {
                        IpAddr::V4(ipv4) => {
                            // 过滤回环地址
                            if !ipv4.is_loopback() {
                                //println!("IPv4: {} (接口: {})", ipv4, iface.name);
                                if !first_ip {
                                    first_ip = true;
                                    active_ip = addr;
                                }
                            }
                        }
                        IpAddr::V6(ipv6) => {
                            // 过滤回环地址和链路本地地址
                            if !ipv6.is_loopback() && !ipv6.is_unicast_link_local() {
                                if !first_ip {
                                    first_ip = true;
                                    active_ip = addr;
                                }
                                //println!("IPv6: {} (接口: {})", ipv6, iface.name);
                            }
                        }
                    }
                }
            }
        }
        Err(e) => {
            eprintln!("获取网络接口失败: {}", e);
        }
    } 

    let port = 18516;
    // 构建URL
    let url = format!("http://{}:{}", active_ip, port);

    url
}

// 获取配置文件路径
fn get_qr_config_path() -> std::io::Result<PathBuf> {
    let mut config_dir = dirs::config_dir()
        .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::Other, "无法获取配置目录"))?;
    config_dir.push("sheisright");
    config_dir.push("qr.toml");
    //println!("config dir of qr {:?}", config_dir); 
    Ok(config_dir)
}

// 读取配置文件
pub fn read_qr_config(path: &std::path::Path) -> io::Result<String> {
    let mut file = std::fs::File::open(path)?;
    let mut contents = String::new();
    //println!("read from {:?}", path); 
    file.read_to_string(&mut contents)?;
    
    // 解析 TOML 内容
    let config: QRConfig = toml::from_str(&contents)
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
    
    Ok(config.qr_code_url)
}

// 定义配置结构
#[derive(Debug, Serialize, Deserialize)]
struct QRConfig {
    qr_code_url: String,
}

// 定义配置结构
#[derive(Debug, Serialize, Deserialize)]
pub struct HttpRootConfig {
    pub http_root_url: String,
}

pub fn get_qr_url() -> String {
    let qr_code_url = match get_qr_config_path() {
        Ok(path) => {
            if path.exists() {
                match read_qr_config(&path) {
                    Ok(url) => url, // 假设config有qr_code_url字段
                    Err(_) => get_local_url(),
                }
            } else {
                get_local_url() // 处理文件不存在的情况
            }
        },
        Err(_) => get_local_url(),
    };
    return qr_code_url;
}
pub fn get_hotspot_url() -> String {
    let qr_code_url = get_qr_url();
    let upload_url = build_upload_url();
    
    // 打开目录，处理可能的错误
    let entries = match fs::read_dir(&upload_url) {
        Ok(dir) => dir,
        Err(_) => return "".to_string(),
    };
    
    let mut files_with_mtime = Vec::new();
    
    for entry in entries {
        // 处理条目读取错误
        let entry = match entry {
            Ok(e) => e,
            Err(_) => continue,
        };
        
        // 显式绑定路径到变量，延长其生命周期
        let path = entry.path();
        
        // 检查是否为文件
        if path.is_file() {
            // 获取文件元数据以获取修改时间
            let metadata = match entry.metadata() {
                Ok(meta) => meta,
                Err(_) => continue,
            };
            
            // 获取最后修改时间
            let modified_time = match metadata.modified() {
                Ok(time) => time,
                Err(_) => continue,
            };
            
            // 从路径获取文件名
            let file_name = match path.file_name() {
                Some(name) => name,
                None => continue,
            };
            
            // 转换文件名到字符串
            let file_name_str = match file_name.to_str() {
                Some(s) => s,
                None => continue,
            };
            
            // 将文件信息存入向量，用于后续排序
            files_with_mtime.push((modified_time, file_name_str.to_string()));
        }
    }
    
    // 按修改时间降序排序，最新的文件排在前面
    files_with_mtime.sort_by(|a, b| b.0.cmp(&a.0));
    
    // 返回最新文件的URL，如果存在的话
    if let Some((_, file_name_str)) = files_with_mtime.first() {
        let file_url = format!("{}/download/{}/{}", qr_code_url, upload_url, file_name_str);
        println!("最新文件URL: {}", file_url);
        file_url
    } else {
        println!("未找到任何文件");
        "".to_string()
    }
}

     
pub fn generate_qr_from_config() -> String {

    //println!("generate qr from config");
    let qr_code_url = get_qr_url();
    let qr_png_data: Vec<u8> = qrcode_generator::to_png_to_vec(&qr_code_url, QrCodeEcc::Low, 1024).unwrap();
    // 将二进制数据编码为Base64字符串
    let base64_str = base64::engine::general_purpose::STANDARD.encode(&qr_png_data);

    // 构建完整的data URI
    let data_uri = format!("data:image/png;base64,{}", base64_str);

    data_uri   
}

pub fn generate_qr_from_str(url: &str) -> String {

    //println!("generate qr from config");
    let qr_code_url = url.to_string();

    let qr_png_data: Vec<u8> = qrcode_generator::to_png_to_vec(&qr_code_url, QrCodeEcc::Low, 1024).unwrap();
    // 将二进制数据编码为Base64字符串
    let base64_str = base64::engine::general_purpose::STANDARD.encode(&qr_png_data);

    // 构建完整的data URI
    let data_uri = format!("data:image/png;base64,{}", base64_str);

    data_uri   
}
// 获取配置文件路径
fn get_http_root_config_path() -> std::io::Result<PathBuf> {
    let mut config_dir = dirs::config_dir()
        .ok_or_else(|| std::io::Error::new(std::io::ErrorKind::Other, "无法获取配置目录"))?;
    config_dir.push("sheisright");
    config_dir.push("httproot.toml");
    //println!("config dir of http-root {:?}", config_dir); 
    Ok(config_dir)
}

pub fn get_http_root_url() -> String {
    let root_url = match get_http_root_config_path() {
        Ok(path) => {
            if path.exists() {
                match read_http_root_config(&path) {
                    Ok(url) => url, // 假设config有qr_code_url字段
                    Err(_) => get_current_dir(),
                }
            } else {
                get_current_dir() // 处理文件不存在的情况
            }
        },
        Err(_) => get_current_dir(),
    };
    //println!("root_url {root_url}");
    return root_url;
}

// 读取配置文件
pub fn read_http_root_config(path: &std::path::Path) -> io::Result<String> {
    let mut file = std::fs::File::open(path)?;
    let mut contents = String::new();
    //println!("read from {:?}", path); 
    file.read_to_string(&mut contents)?;
    
    // 解析 TOML 内容
    let config: HttpRootConfig = toml::from_str(&contents)
        .map_err(|e| io::Error::new(io::ErrorKind::InvalidData, e))?;
    
    Ok(config.http_root_url)
}

pub fn get_system_root() -> PathBuf {
    if cfg!(windows) {
        // Windows 系统
        match std::env::current_dir() {
            Ok(mut current_dir) => {
                // 逐级向上直到根目录
                while let Some(parent) = current_dir.parent() {
                    if parent.as_os_str().is_empty() {
                        break;
                    }
                    current_dir = parent.to_path_buf();
                }
                current_dir
            }
            Err(_) => PathBuf::from("C:\\"), // 默认使用 C 盘
        }
    } else {
        // Unix 系统
        PathBuf::from("/")
    }
}

fn get_current_dir() -> String {
    let current_dir = match env::current_dir() {
        Ok(dir) => dir,
        Err(_) => return String::new(),
    };

    #[cfg(target_os = "windows")]
    {
        // 在 Windows 上，将路径中的单斜杠替换为双斜杠
        let path_str = current_dir.to_string_lossy().into_owned();
        path_str.replace('\\', "\\\\")
    }

    #[cfg(not(target_os = "windows"))]
    {
        // 在非 Windows 系统上，直接返回路径字符串
        current_dir.to_string_lossy().into_owned()
    }
}

// 保存 URL 到配置文件的函数
pub fn save_http_root_url_to_config(url: &str) -> std::io::Result<()> {
    println!("saving http root...");
    let absolute_path = path_normalization(ensure_root_path(url));
    let config_path = get_http_root_config_path()?;

    // 创建配置目录（如果不存在）
    if let Some(parent) = config_path.parent() {
        fs::create_dir_all(parent)?;
    }
    println!("save to {:?}", config_path);   
    // 创建配置结构
    let config = HttpRootConfig {
        http_root_url: absolute_path,
    };
    
    // 序列化为 TOML 格式
    let toml_data = toml::to_string(&config).map_err(|e| {
        std::io::Error::new(std::io::ErrorKind::Other, format!("序列化失败: {}", e))
    })?;
    
    // 写入文件
    let mut file = File::create(config_path)?;
    file.write_all(toml_data.as_bytes())?;
    
    Ok(())
}

/// 检查路径是否包含根路径，如果不包含则添加
pub fn ensure_root_path(path: impl AsRef<Path>) -> PathBuf {
    let path = path.as_ref();
    let system_root = get_system_root();
    
    // 检查路径是否已经是绝对路径（包含根）
    if path.is_absolute() {
        return path.to_path_buf();
    }
    
    // 对于相对路径，拼接系统根路径
    let mut full_path = system_root;
    full_path.push(path);
    full_path
}

pub fn path_normalization(current_dir: PathBuf) -> String {

    #[cfg(target_os = "windows")]
    {
        // 在 Windows 上，将路径中的单斜杠替换为双斜杠
        let path_str = current_dir.to_string_lossy().into_owned();
        path_str.replace('\\', "\\\\")
    }

    #[cfg(not(target_os = "windows"))]
    {
        // 在非 Windows 系统上，直接返回路径字符串
        current_dir.to_string_lossy().into_owned()
    }
}

pub fn build_upload_url() -> String {
    let root_url = crate::util::get_http_root_url();
    // 处理 URL 末尾是否有斜杠
    let root = if root_url.ends_with('/') {
        root_url
    } else {
        format!("{}/", root_url)
    };
    // 拼接 uploads 目录
    format!("{}{}", root, "uploads")
}